package com.winit.openapi.isp.controller;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;

import com.alibaba.fastjson.JSONObject;
import com.winit.common.spi.context.CommandContext;
import com.winit.oms.spi.isp.ISPFeeCalculatorService;
import com.winit.oms.spi.isp.command.ISPFeeQueryCommand;
import com.winit.oms.spi.vo.ISPFeeCalculatorEstimateResult;
import com.winit.oms.spi.vo.ISPFeeCalculatorResult;
import com.winit.openapi.constants.ErrorCode;
import com.winit.openapi.controller.BaseController;
import com.winit.openapi.exception.ApiException;
import com.winit.openapi.model.RequestMsg;
import com.winit.openapi.model.ResponseMsg;
import com.winit.openapi.util.ValidateUtil;
import com.winit.pms.spi.winit.command.WinitRuleQueryCommand;
import com.winit.pms.spi.winit.vo.DeclareGoods;

@RequestMapping(value="/isp/feeCalc")
@Controller
public class ISPFeeCalculatorController extends BaseController {
    
    @Resource
    private ISPFeeCalculatorService iSPFeeCalculatorService;

    
    @RequestMapping(value = "/query")
    public String query(@ModelAttribute RequestMsg requestMsg, @ModelAttribute ResponseMsg responseMsg) {

        Object obj = requestMsg.getData();
        
        if(!(obj instanceof JSONObject)){
            throw new ApiException(ErrorCode.FIELD_TYPE_ERROR, "data");
        }

        JSONObject json = (JSONObject) obj;
        validateQueryParam(json);
        ISPFeeQueryCommand command = buildISPFeeQueryCommand(json);
        
        List<ISPFeeCalculatorResult> iSPFeeCalculatorResultList = iSPFeeCalculatorService.queryISPFeeList(command);

        responseMsg.setData(iSPFeeCalculatorResultList);
        return SUCCESS;
    }
    
    @RequestMapping(value = "/estimate")
    public String estimate(@ModelAttribute RequestMsg requestMsg, @ModelAttribute ResponseMsg responseMsg) {

        Object obj = requestMsg.getData();
        
        if(!(obj instanceof JSONObject)){
            throw new ApiException(ErrorCode.FIELD_TYPE_ERROR, "data");
        }

        JSONObject json = (JSONObject) obj;
        validateEstimateQueryParam(json);
        ISPFeeQueryCommand command = buildISPFeeEstimateQueryCommand(json);
        
        ISPFeeCalculatorEstimateResult result = iSPFeeCalculatorService.queryISPEstimateFee(command);
        responseMsg.setData(result);
        return SUCCESS;
    }
    
    private ISPFeeQueryCommand buildISPFeeQueryCommand(JSONObject json){
        ISPFeeQueryCommand command = new ISPFeeQueryCommand();
        command.setCtx(CommandContext.getContext());
        
        command.setWarehouseCode(json.getString("warehouseCode"));
        command.setBuyerCountryCode(json.getString("buyerCountryCode"));
        command.setBuyerPostcode(json.getString("buyerPostcode"));
        command.setLength(json.getBigDecimal("length"));
        command.setWidth(json.getBigDecimal("width"));
        command.setHeight(json.getBigDecimal("height"));
        command.setWeight(json.getBigDecimal("weight"));
//        command.setMerchandiseName(json.getString("merchandiseName"));
        
        List<DeclareGoods> declareGoodsList = new ArrayList<DeclareGoods>();
        DeclareGoods good = new DeclareGoods();
        good.setDeclareValueTotal(json.getBigDecimal("declareValueTotal"));
        declareGoodsList.add(good);
        command.setDeclareGoodsList(declareGoodsList);
        
        return command;
    }
    
    private ISPFeeQueryCommand buildISPFeeEstimateQueryCommand(JSONObject json){
        ISPFeeQueryCommand command = new ISPFeeQueryCommand();
        command.setCtx(CommandContext.getContext());
        
        command.setWarehouseCode(json.getString("warehouseCode"));
        command.setBuyerCountryCode(json.getString("buyerCountryCode"));
        command.setBuyerPostcode(json.getString("buyerPostcode"));
        command.setLength(json.getBigDecimal("length"));
        command.setWidth(json.getBigDecimal("width"));
        command.setHeight(json.getBigDecimal("height"));
        command.setWeight(json.getBigDecimal("weight"));
        command.setWinitProductCode(json.getString("winitProductCode"));
        
        List<DeclareGoods> declareGoodsList = new ArrayList<DeclareGoods>();
        DeclareGoods good = new DeclareGoods();
        good.setDeclareValueTotal(json.getBigDecimal("declareValueTotal"));
        declareGoodsList.add(good);
        command.setDeclareGoodsList(declareGoodsList);
        
        return command;
    }
    
    private void validateQueryParam(JSONObject json){
        ValidateUtil.validNotNull(json, "warehouseCode");
        ValidateUtil.validMaxLength(json, "warehouseCode", 50);
        
        ValidateUtil.validNotNull(json, "buyerCountryCode");
        ValidateUtil.validMaxLength(json, "buyerCountryCode", 50);
        
        ValidateUtil.validNotNull(json, "buyerPostcode");
        ValidateUtil.validMaxLength(json, "buyerPostcode", 50);
        
        ValidateUtil.validNotNull(json, "length");
        ValidateUtil.validBigDecimal(json, "length");
        ValidateUtil.validatePrecision(json, "length",4,2);
        
        ValidateUtil.validNotNull(json, "width");
        ValidateUtil.validBigDecimal(json, "width");
        ValidateUtil.validatePrecision(json, "width",4,2);
        
        ValidateUtil.validNotNull(json, "height");
        ValidateUtil.validBigDecimal(json, "height");
        ValidateUtil.validatePrecision(json, "height",4,2);
        
        ValidateUtil.validNotNull(json, "weight");
        ValidateUtil.validBigDecimal(json, "weight");
        ValidateUtil.validatePrecision(json, "weight",4,4);
        
//        ValidateUtil.validNotNull(json, "merchandiseName");
//        ValidateUtil.validMaxLength(json, "merchandiseName", 255);
        
        ValidateUtil.validNotNull(json, "declareValueTotal");
        ValidateUtil.validBigDecimal(json, "declareValueTotal");
        ValidateUtil.validatePrecision(json, "declareValueTotal",4,2);
    }
    
    private void validateEstimateQueryParam(JSONObject json){
        ValidateUtil.validNotNull(json, "warehouseCode");
        ValidateUtil.validMaxLength(json, "warehouseCode", 50);
        
        ValidateUtil.validNotNull(json, "buyerCountryCode");
        ValidateUtil.validMaxLength(json, "buyerCountryCode", 50);
        
        ValidateUtil.validNotNull(json, "buyerPostcode");
        ValidateUtil.validMaxLength(json, "buyerPostcode", 50);
        
        ValidateUtil.validNotNull(json, "length");
        ValidateUtil.validBigDecimal(json, "length");
        ValidateUtil.validatePrecision(json, "length",4,2);
        
        ValidateUtil.validNotNull(json, "width");
        ValidateUtil.validBigDecimal(json, "width");
        ValidateUtil.validatePrecision(json, "width",4,2);
        
        ValidateUtil.validNotNull(json, "height");
        ValidateUtil.validBigDecimal(json, "height");
        ValidateUtil.validatePrecision(json, "height",4,2);
        
        ValidateUtil.validNotNull(json, "weight");
        ValidateUtil.validBigDecimal(json, "weight");
        ValidateUtil.validatePrecision(json, "weight",4,4);
        
        ValidateUtil.validNotNull(json, "winitProductCode");
        ValidateUtil.validMaxLength(json, "winitProductCode", 60);
        
        ValidateUtil.validNotNull(json, "declareValueTotal");
        ValidateUtil.validBigDecimal(json, "declareValueTotal");
        ValidateUtil.validatePrecision(json, "declareValueTotal",4,2);
    }
    
    @RequestMapping(value = "/getLimitData")
    public String getLimitData(@ModelAttribute RequestMsg requestMsg, @ModelAttribute ResponseMsg responseMsg) {

        Object obj = requestMsg.getData();
        
        if(!(obj instanceof JSONObject)){
            throw new ApiException(ErrorCode.FIELD_TYPE_ERROR, "data");
        }

        JSONObject json = (JSONObject) obj;
        ValidateUtil.validNotNull(json, "winitProductCode");
        ValidateUtil.validMaxLength(json, "winitProductCode", 60);
        
        WinitRuleQueryCommand command = new WinitRuleQueryCommand();
        command.setWinitProductCode(json.getString("winitProductCode"));
        
        Map<String, Object> map = iSPFeeCalculatorService.getLimitData(command);

        responseMsg.setData(map);
        return SUCCESS;
    }
}
